package cn.java75.sp.util;

import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.*;
import java.util.logging.Logger;

/**
 * @author oldliu
 * @since 1.0
 */
public class JwtUtil {
    private static Logger logger = Logger.getLogger("cn.java75.sp.util.JwtUtil");
    public static final String TOKEN_HEADER = "Authorization";//token的key 也是名 不要写成token这样，要按照规范来
    public static final String TOKEN_PREFIX = "Bearer ";//token值的前缀，这是一种规范 ok
    private static final String SECRET = "mrLang";//你自己定的字符串 别让别人知道，加密时候用   盐
    public static final String FUNCTS = "FUNCTS";//获取用户的功能使用的key
    public static final String USERINFO = "USER";//获取用户使用的key
    private static final long EXPIRATION = 120L;// token的生命周期30分
    /**
     * 创建token令牌 以下为参数都是自定义信息
     * @param loginName  一般我们放用户的唯一标识登录名
     * @param functs 当前用户的功能集合， 本人的rbac权限比较个性化且很负责，一般你们放role角色就可以了
     * @param user 当前用户
     * @return
     */
    public static String createToken(String loginName, List<Object> functs, Users user) {
        Map<String, Object> map = new HashMap<>();
        //当前用户拥有的功能
        //jackson

        map.put(FUNCTS, JSON.toJSONString(functs) );
        //当前用户信息
        map.put(USERINFO, JSON.toJSONString(user));

       String token = Jwts.builder()
                .setClaims(map)
                .setSubject(loginName)//主题  主角是谁？    赋值登录名
                .setIssuedAt(new Date())//设置发布时间，也是生成时间
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION * 1000))//设置过期时间
                .signWith(SignatureAlgorithm.HS256, SECRET).compact();//创建完成
        return token;
    }
   // jwt 如何验证Token是否过期呢？
    // token是否过期
    public static boolean isExpiration(String token) {
        try {
            return getTokenBody(token).getExpiration().before(new Date());
        } catch (Exception e) {
            return true;
        }
    }
    // jwt 如何获取自定义的信息呢？
    // 获取主角，登录名
    public static String getUserName(String token) {
        return getTokenBody(token).getSubject();
    }

    // 获取token中存储的功能
    public static List<Object> getUserFuncts(String token) {
        String str = getTokenBody(token).get(FUNCTS).toString();
        List<Object> list =JSON.parseArray(str);
        return list;
    }

    // 获取token存储的用户
    public static Object getUser(String token) {
        String str = getTokenBody(token).get(USERINFO).toString();
        return JSON.parseObject(str,Users.class);
    }

    // 公共获取自定义数据
    public static Claims getTokenBody(String token) {
        return Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
    }
    //jwt 如何刷新Token呢？
    // 刷新token
    public static String refreshToken(String token) {
        if (isExpiration(token)) {
            logger.info("token刷新失败！！ 过期了！！");
            return null;
        }
        // 获取用户 权限信息
        String functs = getTokenBody(token).get(FUNCTS).toString();
        String user = getTokenBody(token).get(USERINFO).toString();
        String username = getTokenBody(token).getSubject();
        Map<String, Object> map = new HashMap<>();

        map.put(FUNCTS, JSON.toJSONString(functs) );
        //当前用户信息
        map.put(USERINFO, JSON.toJSONString(user));
        token = Jwts.builder().signWith(SignatureAlgorithm.HS256, SECRET).setClaims(map).setSubject(username)
                .setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + EXPIRATION * 1000))
                .compact();
        return token;
    }
}
